﻿package ygg.encoding.amf.type.v3
{
	import j.sus2maj7.encoding.*;
	import ygg.encoding.amf.*;
	import ygg.encoding.amf.type.*;
	
	public class ArrayCodec extends ComplexCodec
	{
		public function ArrayCodec()
		{
			
		}
		/*U29A-value=U29
		; The first (low) bit is a flag with
		; value 1. The remaining 1 to 28
		; significant bits are used to encode the
		; count of the dense portion of the
		; Array.
		//*/
		//array-type = array-marker (U29O-ref | (U29A-value (UTF-8-empty | *(assoc-value) UTF-8-empty) *(value-type)))
		//assoc-value = UTF-8-vr value-type
		override protected function decodeComplex(u:uint, binary:IBinary, context:IContext=null):*
		{
			var retVal:Array = [];
			
			//UTF-8-empty | *(assoc-value) UTF-8-empty
			var assoc:Array = [];
			
			var ctx:AmfContext = AmfContext(context);
			
			var name:String = ctx.nameCodec.decode(binary, context);
			
			while (name.length > 0)
			{
				trace('name=', name);
				
				var v:* = ctx.codecFactory.getDecoder(binary.readUnsignedByte(), ctx).decode(binary, context);
				trace('value=', v);
				
				assoc[name] = v;
				
				name = ctx.nameCodec.decode(binary, context);
			}
			
			
			// u = dense portion
			//*(value-type)
			while (u--)
			{
				trace('name=', retVal.length);
				
				retVal[retVal.length] = ctx.codecFactory.getDecoder(binary.readUnsignedByte(), ctx).decode(binary, context);
				
				trace('value=', retVal[retVal.length-1]);
			}
			
			for (var i:String in assoc)
			{
				retVal[i] = assoc[i];
			}
		
			return retVal;
		}
		
		override protected function encodeComplex(o:Object, b:IBinary, context:IContext=null):void
		{
			var a:Array = o as Array;
			var ctx:AmfContext = AmfContext(context);
			
			//U29A-value
			//u29 dense portion
			//find length of dense portion
			
			var len:int = a.length;
			for (var i:int = 0; i < len; i++)
			{
				if (a[i] == undefined)
				{
					len = i;
					break;
				}
			}
			trace('dense portion len=', len);
			//write dension portion size
			b.writeByte(len << 1 | 1 );
			
			for (var j:* in a)
			{
				trace(j);
				if (isNaN(Number(j)) || Number(j) > len)
				{
					trace('name=', j);
					b.writeBytes( ctx.nameCodec.encode(String(j), context).ba, 1) ;
					
					trace('value=', a[j]);
					b.writeBytes( ctx.codecFactory.getEncoder(a[j], ctx).encode(a[j], context).ba );
				}
			}
			
			//assoc term
			b.writeByte(1);
			
			
			//dense portion
			for (var k:int = 0; k < len; k++)
			{
				trace('name=', k);
				trace('value=', a[k]);
				b.writeBytes( ctx.codecFactory.getEncoder(a[k], ctx).encode(a[k], context).ba );
			}
			
		}
		override protected function getMarker():uint
		{
			return Amf3Marker.ARRAY;
		}
	}
}